<?php
namespace app\controller;

use app\BaseController;
use Exception;
use Lib\Crypt;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Facade\Log;
use think\response\Json;

class Com extends BaseController
{

    private function xml_entities($string) {
        return strtr(
            $string, 
            array(
                "<" => "&lt;",
                ">" => "&gt;",
                '"' => "&quot;",
                "'" => "&apos;",
                "&" => "&amp;",
            )
        );
    }    
    /**
     * 生成世界项
     * @param array $list 数据列表
     * @param int $page 当前页码
     * @return string
     */
    private function makeDocumentList(array $list, int $page): string
{
    $out = '<Results NextCursor="'.($page+1).'">';
    foreach ($list as $v){
        $downUrl = getHostUrl('fileload/'.$v['file_id'], true);
        $type = $this->typeToSC($v['file_type']);
        $cover = getHostUrl($this->xml_entities($v['cover_src']), true);
        $name = explode('.', $v['name']);
        $arr = [];
        for ($i = 0; $i < count($name) - 1; $i++) {
            $arr[] = $name[$i];
        }
        $name = $this->xml_entities(implode('.', $arr));
        $size = $this->xml_entities(filesize($v['path']));
        $level = $v['rate'];
        $uid = $v['uid'];
        $downTimes = $v['down_times'];
        $nickname = $this->xml_entities($v['nickname']);
        $addTime = $v['create_time'];
        $id = $v['id'];
        $boutique = $v['boutique'];
        $modId = $v['mod_id']; // 获取 mod_id
        $modName = $this->xml_entities($v['mod_name']); // 获取 mod_name
        $details = $v['mod_description'];
        $length = 50;
        
        if (mb_strlen($details, 'UTF-8') > $length) {
            $shortenedDetails = mb_substr($details, 0, $length, 'UTF-8') . '...';
        } else {
            $shortenedDetails = $details;
        }
        $shortenedDetails = $this->xml_entities($shortenedDetails);
        // 将 mod_id 和 mod_name 加入到 XML 输出
        $out .= sprintf(
            '<Result Id="%d" UName="%s" Boutique="%d" IsShow="1" Icon="%s" Name="%s" Url="%s" Type="%s" Size="%s" RatingsAverage="%s" UserId="%s" CollectionID="%d" CollectionName="%s" CollectionDetails="%s" ExtraText="(%s人次下载, %s上传于%s)" />',
            $id, $nickname, $boutique, $cover, $name, $downUrl, $type, $size, $level, $uid, $modId, $modName, $shortenedDetails, $downTimes, $nickname, date('Y/m/d', $addTime)
        );
    }
    $out .= "</Results>";
    return $out;
}

    private function getTextFromType($type){
        switch ($type) {
            case 1:return '世界';
            case 2:return '方块材质';
            case 3:return '人物皮肤';
            case 4:return '家具包';
            case 5:return 'Mod';
        }
        return 0;
    }
    private function getTypeFromText($type): int
    {
        switch ($type) {
            case '世界':return 1;
            case '方块材质':return 2;
            case '人物皮肤':return 3;
            case '家具包':return 4;
            case 'Mod':return 5;
        }
        return 0;
    }
    /**
     * 社区内容列表
     */
    public function list()
    {
        $page=request()->post('Cursor',0,'int');
        $SortOrder=request()->post('SortOrder');
        $version=request()->post('Version');
        $type=request()->post('Type');
        $Action=request()->post('Action');
        $FeedbackParameter=request()->post('FeedbackParameter');
        $url=request()->post('Url');
        $api_type=request()->post('Apiv',0,'int');
        $userId=request()->post('UserId');//只看本用户
        $Feedback=request()->post('Feedback');
        $SearchType = request()->post('SearchType');//搜索类型
        $key = request()->post('key');
        $page+=1;
        $inputRaw = file_get_contents("php://input");
        if(!empty($inputRaw) && empty($Action)){
            parse_str($inputRaw,$data);
            if(array_key_exists('Action',$data)) $Action = $data['Action'];
            if(array_key_exists('Feedback',$data)) $Feedback = $data['Feedback'];
            if(array_key_exists('FeedbackParameter',$data)) $FeedbackParameter = $data['FeedbackParameter'];
            if(array_key_exists('Url',$data)) $url = $data['Url'];
            if(array_key_exists('UserId',$data)) $userId = $data['UserId'];
        }
        if($Action=="feedback"){
            $fileId = 0;
            if(!empty($url)){
                $arr = explode('/',$url);
                $fileId = $arr[count($arr)-1];
            }
            //用户评价
            if($Feedback=="Rating"){
                $this->M("file_feedback")->insert(['user_id'=>$userId,'file_id'=>$fileId,'feed_type'=>1,'create_time'=>time(),'content'=>$FeedbackParameter]);
                return pr(200,'rate');
            }
            //用户成功下载
            if($Feedback == "Success"){
//                \think\facade\Log::write("$userId $url 成功下载");
                $this->M("file_feedback")->insert(['user_id'=>$userId,'file_id'=>$fileId,'feed_type'=>3,'create_time'=>time()]);
                return pr(200,'down');
            }
            //用户导入文件失败
            if($Feedback == "ImportFailure"){
//                \think\facade\Log::write("$userId $url 导入失败");
                return pr(200,'im_fail');
            }
            //用户下载失败
            if($Feedback == "DownloadFailure"){
//                \think\facade\Log::write("$userId $url 下载失败");
                return pr(200,'down_fail');
            }
            //记录报告
            if($Feedback == "Report"){
                $this->M("file_feedback")->insert(['user_id'=>$userId,'file_id'=>$fileId,'feed_type'=>2,'create_time'=>time(),'content'=>$FeedbackParameter]);
                return pr(200,'report');
            }
            //体验时间
            if($Feedback == "PlayTime"){
//                \think\facade\Log::write("$userId $url 时间报告 $FeedbackParameter");
                return pr(200,'playtime');
            }
            return pr(300,'未知的回访分支');
        }
        else{
        $fileType = $this->getTypeFromText($type);
        $obj = $this->M('mod_file')->alias('mf');
        $obj->field('0 as boutique,0 as rate,ifnull(d.file_type,5) as file_type,m.id,mf.file_id,f.name,u.nickname,u.id as uid,f.down_times,f.create_time,f.path,m.cover_src,mf.mod_id,m.name as mod_name,m.description as mod_description'); // 加上 mod_id
        $obj->join('files f','f.id = mf.file_id')
            ->join('mod m','m.id = mf.mod_id and m.stat = 1')
            ->join('user u','u.id = m.uid')
            ->group('mf.id');
        $obj->leftJoin('document d','d.id = mf.document_id');
        if($fileType == 5) $obj->where('mf.api_type','=',$api_type);
        if($fileType > 0 && $fileType < 5){
            $obj->where('d.file_type','=',$fileType);
        }
        if(!empty($SearchType)){
            if($SearchType=='ByAuthor'){//按用户名搜索
                $obj->where('u.nickname','like',"%$key%");
            }else if($SearchType=='ByName'){//按资源名称搜索
                $obj->where('f.name','like',"%$key%");
            }
        }
        if(!empty($userId)){
            $u = $this->M('user')->where(['token'=>$userId])->field('id')->find();
            $obj->where('d.uid','=', $u['id']);
        }
        $obj->page($page,10);

        if($SortOrder=='ByRank') {
            //$obj->order('d.rate','desc');
        }
        elseif($SortOrder=='ByBoutique'){
            //$obj->order('d.boutique','desc');
        }
        else{ $obj->order('f.create_time','desc');}
        $list=$obj->select()->toArray();
        return $this->makeDocumentList($list,$page);
        }
    }

    /**
     * 获取公告内容
     */
    public function motd(){
        try {
            $f = $this->M("config")->where(['name' => 'motd'])->find();
            return $f['value'];
        } catch (DataNotFoundException $e) {
            return 'Error 301';
        } catch (ModelNotFoundException $e) {
            return 'Error 302';
        } catch (DbException $e) {
            return 'Error 303';
        }
    }
    function getLoginUserId(){
        $userToken = getAuthCode();
        try {
            $u = $this->M('user')->field('id')->where(['token' => $userToken])->find();
            if(!empty($u)) return $u['id'];
            else return 0;
        } catch (DataNotFoundException | ModelNotFoundException | DbException $e) {
            return 0;
        }
    }
    /**
     * 存档上传
     */
    public function file_upload(){
        $fileContent = file_get_contents("php://input");
        $fileParams = $_SERVER['HTTP_DROPBOX_API_ARG'];
        $fileParams = json_decode($fileParams,true);
        $fileName = $fileParams['path'];
        $fileArr = explode('/',$fileName);
        $fileName = $fileArr[count($fileArr)-1];
        $uid = $this->getLoginUserId();
        if(empty($uid)) pr(300,'请先登陆');
        else{
            $p = saveToFile($fileName,$fileContent,$uid);
            try {
                $f = $this->M("files")->where(['uid' => $uid, 'name' => $fileName])->field('id,path')->find();
                if(empty($f)){
                    $fileId = $this->M("files")->insert(['size'=>filesize($p),'uid'=>$uid,'type'=>0,'down_times'=>0,'create_time'=>time(),'last_modify_time'=>time(),'path'=>$p,'name'=>$fileName],true);
                    $df = false;
                }else{
                    $flag = false;
                    try {
                        if($p != $f['path']){
                           $flag = unlink($f['path']);
                        }
                    }catch(Exception $e){
    
                    }
                    $this->M("files")->where(['id'=>$f['id']])->update(['last_modify_time'=>time(),'path'=>$p]);
                    $fileId = $f['id'];
                    $df = $this->M('document')->where('uid','=',$uid)->where('file_id','=',$f['id'])->find();
                }
                if(empty($df)) $this->M('document')->insert(['uid'=>$uid,'file_id'=>$fileId,'file_type'=>getSCType($fileName)]);
                return pr(200);
            } catch (DataNotFoundException $e) {
                return pr(300);
            } catch (ModelNotFoundException $e) {
                return pr(301);
            } catch (DbException $e) {
                return pr(302);
            }
        }
    }
    
    /**
     * 添加已有文件为游戏内资源
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function add_document(): Json
    {
        $uid = $this->getUid();
        $fileId = request()->post('file_id');
        $fileName = request()->post('file_name');
        if(empty($uid)) pr(300,'请先登陆');
        if(empty($file_name)||empty($fileId)) pr(300,'参数错误');
        $f = $this->M('files')->field('id')->where('id',$fileId)->where('uid',$uid)->find();
        if(empty($f)) return pr(300,'你没有此文件使用权');
        $f = $this->M('document')->field('id')->where('uid',$uid)->where('file_id',$fileId)->find();
        if(empty($f)){
            $docId = $this->M('document')->insert(['uid'=>$uid,'file_id'=>$fileId,'file_type'=>getSCType($fileName)],true);
            return pr(200,'suc',$docId);
        }else{
            return pr(300,'已添加文件，不可重复添加');
        }
    }

    /**
     * 列出用户文件夹列表
     */
    public function list_folder()
    {
        $uid = $this->getLoginUserId();
        $list = $this->M('document')
            ->field("d.file_type,f.path,f.name,create_time")
            ->alias('d')
            ->join('files f','f.id = d.file_id')
            ->where(['d.uid'=>$uid])
            ->select()
            ->toArray();
        $entries = [];
        foreach ($list as $v){
            $size = file_exists($v['path'])?filesize($v['path']):0;
            $entries[]=['path_display'=>$v['name'],'.tag'=>$this->typeToSC($v['file_type']),'server_modified'=>date('Y-m-d H:i:s',$v['create_time']),'size'=>$size];
        }
        return json_encode(['entries'=>$entries]);
    }

    /**
     * 创建存档分享链接
     */
    public function create_shared_link(){
        $param = file_get_contents('php://input');
        $params = json_decode($param,true);
        $uid = $this->getLoginUserId();
        $fileArr = explode('/',$params['path']);
        if(count($fileArr)==0||empty($uid)){
            return json_encode(['url'=>'请登陆']);
        }else{
            $fileName = $fileArr[count($fileArr)-1];
            $fileId = $this->M('files')->field('id')->where('uid',$uid)->where('name',$fileName)->find();
            if(empty($fileId)){
                return json_encode(['url'=>'分享失败,不存在的文件']);
            }else{
                return json_encode(['url'=>getHostUrl('fileload/'.$fileId['id'],true)]);
            }
        }
    }

    /**
     * 服务器列表获取
     * @return false|string
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function serverlist(){
        $version = request()->get('version');
        //获取ID
        $f = $this->M("server_version_list")->where('version','=',$version)->find();
        $list = [];
        if(!empty($f)){
            $list = $this->M("mod_server_detail")
                ->alias('msd')
                ->field("msd.name,msd.ip_addr as ip,msd.level")
                ->join("sc_mod sm",'sm.id = msd.mod_id')
                ->where(['msd.version_id'=>$f['id'],'msd.stat'=>1])
                ->group("msd.id")
                ->select()
                ->toArray();
            foreach ($list as $k=>$v){
                $list[$k]['version'] = $version;
            }
        }
        return json_encode(['list'=>$list]);
    }

    /**
     * 根据文档类型返回英文分类名
     * @param $type
     * @return string
     */
    function typeToSC($type): string
    {
        switch($type){
            case 1:return 'World';
            case 2:return 'BlocksTexture';
            case 3:return 'CharacterSkin';
            case 4:return 'FurniturePack';
            case 5:return 'Mod';
            default:return 'Directory';
        }

    }


    function api(){
        return pr(300,'fail');
    }
    function checkuser(){
        $token = request()->get('token');
        $ip = request()->get('ip');
        $u = $this->M('user')->field('id,nickname,stat')->where('token','=',$token)->find();
        if(!empty($u)) {
            if($u['stat']==0) pr(301,'账号已被锁定');
            else return pr(200,'',$u);
        }
        else return pr(300);
    }
    function checkUser_t(){
        $user = request()->post('user');
        $token = request()->post('token');
        $serverIp = request()->post('server_ip');
        $clientIp = request()->post('client_ip');
        if(empty($user)||empty($token)) return pr(301,'账号或密钥为空');
        $u = $this->M('user')->field('id,nickname,stat,token,password')->where('account',$user)->find();
        $p = Crypt::Decode($u['password']);
        if(!empty($u)) {
            if($u['stat']==0) return pr(301,'账号已被锁定');
            else if(md5($user.'/'.md5($user.$p))==$token) return pr(200,'ok',['id'=>$u['id'],'nickname'=>$u['nickname'],'token'=>md5($u['token'])]);
            else return pr(302,'密钥校验错误');
        }
        else return pr(300);
    }
    function download_file(){
        $uid = $this->getLoginUserId();
        if(empty($uid)) return pr(300,'login required');
        $arg = $_SERVER['HTTP_DROPBOX_API_ARG'];
        $arg = json_decode($arg,true);
        $path = substr($arg['path'],1);
        $q = $this->M("files")->field('id')->where("uid",$uid)->where('name',$path)->find();
        if(!empty($q)) return response()->header(['Location'=>'https://down.schub.top/fileload/'.$q['id']]);
        else return $path;
    }
}
